package com.common.tool;


import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class JwtTool {

    private static final String USERNAME = "username";

    private static final String ID = "id";

    /**
     * 生成token
     *
     * @return
     */
    public static String createSecretJwt(String username, Long id, String access_secretKey, Integer access_expireHours) {
        // 创建JWT的构建器
        JwtBuilder builder = Jwts.builder();
        // 设置JWT载荷
        Map<String, Object> claims = new HashMap<>();
        claims.put(ID, id);
        claims.put(USERNAME, username);
        builder.claims(claims);
        // 得到安全认证信息配置
        builder.expiration(getExpirationTime(access_expireHours));  // 设置过期时间
        // 设置签名密钥  将我们配置的密钥转为Jwt需要的 SecretKey
        builder.signWith(Keys.hmacShaKeyFor(access_secretKey.getBytes()));
        // 设置JWT的签发时间
        builder.issuedAt(new Date());
        // 生成JWT 并返回
        return builder.compact();
    }

    public static String createRefreshJwt(String username, String refresh_secretKey, Integer refresh_expireHours) {
        // 创建JWT的构建器
        JwtBuilder builder = Jwts.builder();
        // 设置JWT载荷
        Map<String, Object> claims = new HashMap<>();
        claims.put(USERNAME, username);
        builder.claims(claims);
        // 得到安全认证信息配置
        builder.expiration(getExpirationTime(refresh_expireHours));  // 设置过期时间
        // 设置签名密钥  将我们配置的密钥转为Jwt需要的 SecretKey
        SecretKey secretKey = Keys.hmacShaKeyFor(refresh_secretKey.getBytes());
        builder.signWith(secretKey);
        // 设置JWT的签发时间
        builder.issuedAt(new Date());
        // 生成JWT 并返回
        return builder.compact();
    }

    /**
     * 获取用户名
     */
    public static String getUsername(String token, String key) {
        // 使用相同的Key解析令牌 得到解析构造器 并且设置相同的Key
        JwtParser parser = Jwts.parser().verifyWith(Keys.hmacShaKeyFor(key.getBytes())).build();
        // 得到解析结果
        Jws<Claims> claimsJws = parser.parseSignedClaims(token);
        // 得到载荷对象
        Claims payload = claimsJws.getPayload();
        // 通过key获取value
        return payload.get(USERNAME, String.class);
    }

    public static Long getId(String token, String key) {
        // 使用相同的Key解析令牌 得到解析构造器 并且设置相同的Key
        JwtParser parser = Jwts.parser().verifyWith(Keys.hmacShaKeyFor(key.getBytes())).build();
        // 得到解析结果
        Jws<Claims> claimsJws = parser.parseSignedClaims(token);
        // 得到载荷对象
        Claims payload = claimsJws.getPayload();
        // 通过key获取value
        return payload.get(ID, Long.class);
    }

    /**
     * 判断token是否过期
     */
    public static boolean validateToken(String token, String key) {
        // 使用相同的Key解析令牌 得到解析构造器 并且设置相同的Key
        JwtParser parser = Jwts.parser().verifyWith(Keys.hmacShaKeyFor(key.getBytes())).build();
        // 得到解析结果
        Jws<Claims> claimsJws = parser.parseSignedClaims(token);
        // 得到载荷对象
        Claims payload = claimsJws.getPayload();
        // 得到过期时间
        Date expiration = payload.getExpiration();
        // 判断是否过期   使用 before 方法比较当前时间和token中的过期时间
        // 如果当前时间在过期时间之前，则返回 true，表示token未过期；否则返回 false，表示token已过期
        return new Date().before(expiration);
    }

    private static Date getExpirationTime(Integer hours) {
        return new Date(System.currentTimeMillis() + hours * 60 * 60 * 1000);
    }

}